package examples;

import cern.colt.list.tint.IntArrayList;

import com.jom.DoubleMatrixND;
import com.jom.OptimizationProblem;

public class GAB_ILP {

	public static void main(String[] args)
	{	
		int N = 7;
		int T = 350;
		double distancia[][] = new double [N][N];
		distancia[0] = new double[] {  0, 405, 250, 375, 340, 165, 410};
		distancia[1] = new double[] {405,   0, 155, 245, 215, 240, 375};
		distancia[2] = new double[] {250, 155,   0, 400, 370, 395, 220};
		distancia[3] = new double[] {375, 245, 400,   0, 435, 485, 620};
		distancia[4] = new double[] {340, 215, 370, 435,   0, 455, 590};
		distancia[5] = new double[] {165, 240, 395, 485, 455,   0, 305};
		distancia[6] = new double[] {410, 375, 220, 620, 590, 305,   0};
		
		//double GAB[] = {1/125, 1/80, 1/80, 1/45, 1/45, 1/80, 1/45};
		double GAB[] = {80, 125, 125, 222, 222, 125, 222};
		//double GAB[] = {1000, 2000, 3000, 5000, 6000, 4000, 7000};
		
		OptimizationProblem op = new OptimizationProblem();
		op.setInputParameter( "gab", GAB, "row");
		op.addDecisionVariable( "c", true, new int[] {1,N}, 0, 1);
		
		//op.setObjectiveFunction( "minimize", "sum(c)" );
		op.setObjectiveFunction( "minimize", "sum(gab .* c)" );
		
		for( int i = 0; i < N; i++ )
		{
			String string = new String();
			boolean control = false;
			
			for( int j = 0; j < N; j++ )
				if( distancia[i][j] <= T )
					if( control == false )
					{
						string += "c(" + j + ")";
						control = true;
					}
					else
						string += " + c(" + j + ")";
				
			
			op.addConstraint( string + " >= 1" );
		}
		
	  	op.solve("glpk");

		if (!op.solutionIsOptimal ()) throw new RuntimeException ("An optimal solution was not found");
		
		DoubleMatrixND c = op.getPrimalSolution( "c" );
		
		op = new OptimizationProblem();
		op.setInputParameter( "d", distancia );
		op.addDecisionVariable( "x", true, new int[] {N,N}, 0, 1);
		op.setObjectiveFunction( "minimize", "sum(d .* x)" );
		
		for( int i = 0; i < N; i++ )
			if( c.get( i ) == 0 )
				op.addConstraint( "sum(x(" + i + ",all)) == 0" );
		
		for( int i = 0; i < N; i++ )
			for( int j = 0; j < N; j++ )
				if( c.get( i ) == 1 && c.get( j ) == 1 )
					op.addConstraint( "sum(x(" + i + "," + j + ")) == 0" );
		
		op.addConstraint( "sum(d .* x) >= 1" );
		
		IntArrayList indexList = new IntArrayList();
		c.getNonZeros( indexList, null );
		op.addConstraint( "sum(x) == " + ( N - indexList.size() ) );
		
		op.solve( "glpk" );

		if (!op.solutionIsOptimal ()) throw new RuntimeException ( "An optimal solution was not found" );
		
		DoubleMatrixND x = op.getPrimalSolution( "x" );
		op.setInputParameter( "x", x );		
		
		for( int i = 0; i < N; i++ )
			for( int j = 0; j < N; j++ )
				if( op.parseExpression( "x("+i+","+j+")" ).evaluate().toValue() == 1 )
					System.out.println( "pair("+i+","+j+"): " + op.parseExpression( "d("+i+","+j+")" ).evaluate().toValue() );
		
		System.out.println( "Total delay: " + op.getOptimalCost() );
	}

}
